/**
 * 请求超频拦截
 * @author 木人心
 * @version 1.0.0
 */
import { CancelTokenPending } from '@utils/request/type'
import { cancelTokenConfig } from '@utils/request/config'
import axios, { AxiosRequestConfig } from 'axios'
import { Log, LogLevelEnum } from '@utils/log'
import { FrequencyMessage } from '@utils/request/message'

const cancelTokenPending: Record<string, CancelTokenPending> = {}
const {
  recordFrequency,
  warningThreshold,
  errorThreshold
} = cancelTokenConfig
export function cancelTokenHandle (config: AxiosRequestConfig, logId?: number) {
  // 判断请求地址,不拦截非'/'开头的请求,如其他服务器地址'http://www.xxx.com/'
  if (config.url && config.url.charAt(0) !== '/') return
  // 包含noCancel不拦截
  if (config.noCancel) return

  // 生成记录key
  const key = `${config.url}&${config.method}&${JSON.stringify(config.data)}&${JSON.stringify(config.params)}`
  config.cancelToken = new axios.CancelToken(canceler => {
    if (config.cancelHook) config.cancelHook(canceler)
    // 如果已经被记录,验证是否可再次请求
    if (cancelTokenPending[key]) {
      const pending = cancelTokenPending[key]
      // 如果未超时,拦截请求,并更新拦截时间,否则删除记录
      if (Date.now() - pending.time <= recordFrequency) {
        // 连续已发起请求，给出警告
        if (++pending.count >= warningThreshold) {
          FrequencyMessage.warning('您的操作过快，请不要频繁操作')
        }
        // 连续发起请求，取消重复请求
        if (++pending.count >= errorThreshold) {
          canceler('Cancelled your repeated config')
          const errorTip = '您频繁请求过多，请求已拦截'
          logId && Log.update({
            id: logId,
            logLevel: LogLevelEnum.WARN,
            canceler: errorTip
          })
          FrequencyMessage.error(errorTip)
        }
        // 更新时间戳
        pending.time = Date.now()
      } else {
        // 删除对应的请求记录，重新发起请求
        delete cancelTokenPending[key]
      }
    }
    if (!cancelTokenPending[key]) {
      // 记录当前的请求
      cancelTokenPending[key] = {
        time: Date.now(),
        count: 0
      }
    }
  })
}
